package com.daervin.svc.service.impl;

import com.daervin.svc.common.utils.JsonUtil;
import com.daervin.svc.service.ILocalCacheService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
 * @author daervin
 * @date 2019/12/6
 */
@Service
public class LocalCacheServiceImpl implements ILocalCacheService {
    private Cache<String, String> cache = null;
    private static final int maxSize = 10000;

    private Cache<String, String> getCacheInstance() {
        if (cache == null) {
            synchronized (this) {
                if (cache == null) {
                    CacheBuilder cacheBuilder = CacheBuilder.newBuilder()
                            .maximumSize(maxSize).expireAfterWrite(1, TimeUnit.DAYS);
                    cache = cacheBuilder.removalListener(getRemovalListener()).build();
                }
            }
        }
        return cache;
    }

    /**
     * key被移除监听器
     *
     * @return
     */
    private RemovalListener<String, String> getRemovalListener() {
        return new RemovalListener<String, String>() {
            public void onRemoval(RemovalNotification<String, String> notification) {
                String key = notification.getKey();
            }
        };
    }

    /**
     * 清空本地缓存
     */
    @Override
    public void clearAll() {
        this.getCacheInstance().invalidateAll();
    }

    /**
     * 重置key
     *
     * @param key
     * @param value
     */
    @Override
    public void put(String key, String value) {
        try {
            getCacheInstance().put(key, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取缓存值
     *
     * @param key
     * @return
     * @throws Exception
     */
    @Override
    public <V> V getValue(String key, Class<V> vClass, Callable<String> valueLoader) {
        try {
            String value = getCacheInstance().get(key, valueLoader);
            if (value == null) {
                return null;
            }
            return JsonUtil.toObject(value, vClass);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public <V> V getValue(String key, TypeReference<V> jsonTypeReference, Callable<String> valueLoader) {
        try {
            String value = getCacheInstance().get(key, valueLoader);
            if (StringUtils.isBlank(value)) {
                return null;
            }
            return JsonUtil.toObject(value, jsonTypeReference);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
